package com.szyjjk.imageCrawler;

import com.szyjjk.entity.SysImageCrawler;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @program: hyybypt
 * @description: FTP工具类
 * @author: yangyue
 * @create: 2019-07-22 15:41
 */
public class FTPUtil {

    /**
     * FTP端口
     **/
    private static final int FTP_PORT = 21;
    /**
     * 本地字符编码
     **/
    private static String localCharset = "GBK";

    /**
     * FTP协议里面，规定文件名编码为iso-8859-1
     **/
    private static String serverCharset = "ISO-8859-1";

    /**
     * UTF-8字符编码
     **/
    private static final String CHARSET_UTF8 = "UTF-8";

    /**
     * OPTS UTF8字符串常量
     **/
    private static final String OPTS_UTF8 = "OPTS UTF8";

    /**
     * FTPClient对象
     **/
    private static FTPClient ftpClient = null;

    //其他数据中 返回数据集合
//    private static List<String> fileH2bList = new ArrayList<>();
    //最新的 数据集合+对应的时间
    private static Map<String, Date> dateAndData = new HashMap<>();

    //线程锁
    static Lock lockThread = new ReentrantLock();

    /**
     * @return java.util.List<java.lang.String>
     * @Author yangyue
     * @Description //TODO  Aviso返回当天可下载的数据
     * @Date 16:03 2019/9/17
     * @Param [ftpPath, fileFTPPath, usrname, usrpwd, Mestype, satellite]    satellite 1 是aviso 2 是Himiwari 3是Himiwari-HW
     **/
    public static List<String> getfileList(String ftpPath, String fileFTPPath, String usrname, String usrpwd, String Mestype, int satellite) {
        // 登录FTP
        login(ftpPath, FTP_PORT, usrname, usrpwd, Mestype);
        List<String> fileInfoList = new ArrayList<>();
        if (ftpClient != null) {
            try {
                String path = changeEncoding(fileFTPPath);
                // 判断是否存在该目录
                if (!ftpClient.changeWorkingDirectory(path)) {
                    CrawlerTool.systemout(fileFTPPath + "该目录不存在", Mestype);
                    return null;
                }
                ftpClient.enterLocalPassiveMode();  // 设置被动模式，开通一个端口来传输数据
                String[] fs = ftpClient.listNames();
                // 判断该目录下是否有文件
                if (fs == null || fs.length == 0) {
                    CrawlerTool.systemout(fileFTPPath + "该目录下没有文件", Mestype);
                    return fileInfoList;
                }
                FTPFile[] files = ftpClient.listFiles();
                CrawlerTool.systemout("获取" + files.length + "条数据！", Mestype);

                for (int i = 0; i < files.length; i++) {
                    //根据时差规矩+8小时
                    Calendar rightNow = Calendar.getInstance();
                    rightNow.setTime(files[i].getTimestamp().getTime());
                    rightNow.add(Calendar.HOUR_OF_DAY, +8);
                    Date nowDate = rightNow.getTime();
                    SimpleDateFormat simpleDateFormatNew = new SimpleDateFormat("yyyy-MM-dd");
//                    System.out.println(simpleDateFormatNew.format(nowDate));
                    if (CrawlerTool.isToday(nowDate)) {
                        // 1 是Avios
                        // 2 是Himiwari
                        if (satellite == 2) {
                            if (files[i].getSize() > (1024 * 1024 * 300)) {
                                fileInfoList.add(files[i].getName());
                            }
                        } else if (satellite == 1) {
                            fileInfoList.add(files[i].getName());
                        }
                    }
                }
            } catch (IOException e) {
                CrawlerTool.systemout("获取文件失败！", Mestype);
                e.printStackTrace();
                return null;
            } finally {
                closeConnect(Mestype);
            }
        }
        return fileInfoList;
    }

    /**
     * 连接FTP服务器
     *
     * @param address  地址，如：127.0.0.1
     * @param port     端口，如：21
     * @param username 用户名，如：root
     * @param password 密码，如：root
     */
    private static void login(String address, int port, String username, String password, String type) {
//        OtherUtil.sysOut("开始登陆FTP服务器",1);
        ftpClient = new FTPClient();
        try {
            ftpClient.connect(address, port);
            ftpClient.login(username, password);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                closeConnect(type);
            }
        } catch (Exception e) {
            CrawlerTool.systemout("FTP登录失败", type);
            e.printStackTrace();
        }
        CrawlerTool.systemout("登陆FTP服务器成功", type);
    }


    /**
     * @return java.util.List<java.lang.String>
     * @Author yangyue
     * @Description //TODO
     * @Date 14:59 2019/12/6
     * @Param [ftpPath 下载地址, fileFTPPath, usrname, usrpwd, Mestype, satellite]
     **/
    public static List<String> getListH2B(SysImageCrawler crawler) {
        //通过ftp_url 判断，如果是NULL 哪就说明是无序的，
        // 需要把所有文件都拿出来便利循环，如果有YYYYMM就说按照时间格式去判断
        int index = crawler.getDownloadUrl().indexOf("/");
        String BeginUrl = crawler.getDownloadUrl().substring(0, index);     //开始链接 如：ftp://128.5.6.205/
        String EndUrl = "";       //结束链接 如：HIMAWARI8/2019/1206/   组合起来就 正确的链接
        if (crawler.getFtpUrl() == null) {
            //无序，需要全部获取数据 不要    SimpleDateFormat 去格式化文件夹
            EndUrl = crawler.getDownloadUrl().substring(index);
        } else {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(crawler.getFtpUrl());
            //有序 需要格式化 文件夹 需要减8小时
            EndUrl = crawler.getDownloadUrl().substring(index) + simpleDateFormat.format(CrawlerTool.setTime(new Date(), 0, 0, 0, -8, 0));
        }
        lockThread.lock();      //锁住------
//        fileH2bList = new ArrayList<>();  //初始化
        dateAndData = new HashMap<>();    //初始化
        // 登录FTP
        login(BeginUrl, FTP_PORT, crawler.getFtpName(), crawler.getFtpPwd(), crawler.getSatellite());
        try {
            if (ftpClient != null) {
                String path = changeEncoding(EndUrl);
                // 判断是否存在该目录
                if (!ftpClient.changeWorkingDirectory(path)) {
                    CrawlerTool.systemout(EndUrl + "该目录不存在", crawler.getSatellite());
                    return null;
                }
                ftpClient.enterLocalPassiveMode();  // 设置被动模式，开通一个端口来传输数据
                Listf("/", crawler.getFtpUrl()); //  需要不断便利，便利下面所有文件夹不断便利循环查询数据

            }
        } catch (IOException e) {
            CrawlerTool.systemout("获取文件失败！", crawler.getSatellite());
            e.printStackTrace();
            return null;
        } finally {
            closeConnect(crawler.getSatellite());
            lockThread.unlock();//解锁------
        }

        CrawlerTool.systemout("获取" + dateAndData.size() + "条数据！", crawler.getSatellite());
        //在这里对获取到的数据进行处理，然后返回需要下载的数据
        List<String> resultList=new ArrayList<>();
        for(Map.Entry<String, Date> entry : dateAndData.entrySet()){
            String mapKey = entry.getKey();
             //从这开始进行筛选处理程序
            String sp=crawler.getSatellite();
            if("Himiwari8(FTP)".equals(sp)){
                //处理一组数据
                Date mapValue = entry.getValue();
            }else{
                //不做处理的全部下载
                if(mapKey.startsWith("/")){
                    //去除开头的斜杠
                    mapKey=mapKey.substring(1);
                }
                resultList.add(mapKey);
            }
        }
        return resultList;
    }

    /**
     * @return void
     * @Author yangyue
     * @Description //TODO 便利所有文件夹和文件
     * @Date 11:43 2019/12/9
     * @Param [pathName, judge]
     **/
    public static void Listf(String pathName, String judge) throws IOException {

        if (pathName.startsWith("/") && pathName.endsWith("/")) {
            //更换目录到当前目录
            if (!"/".equals(pathName)) {
                ftpClient.changeWorkingDirectory(pathName);
            }
            FTPFile[] files = ftpClient.listFiles();
            for (FTPFile file : files) {
                if (file.isFile()) {
                    //如果是文件
                    Calendar rightNow = Calendar.getInstance();
                    rightNow.setTime(file.getTimestamp().getTime());
                    rightNow.add(Calendar.HOUR_OF_DAY, +8);
                    Date nowDate = rightNow.getTime();
                    if (CrawlerTool.isToday(nowDate)) {
//                        fileH2bList.add(pathName + file.getName());
                        dateAndData.put(pathName + file.getName(), nowDate);
                    } else if (file.isDirectory()) {
                        if (!".".equals(file.getName()) && !"..".equals(file.getName())) {
                            if (judge == null) {
                                //判断交到这里来处理 ，是否需要便利接下里的文件夹
                                Listf(pathName + file.getName() + "/", judge);
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 关闭FTP连接
     */
    private static void closeConnect(String type) {
        if (ftpClient != null && ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
            } catch (IOException e) {
                CrawlerTool.systemout("关闭FTP连接失败", type);
                e.printStackTrace();
            }
        }
    }

    /**
     * FTP服务器路径编码转换
     *
     * @param ftpPath FTP服务器路径
     * @return String
     */
    private static String changeEncoding(String ftpPath) {
        String directory = null;
        try {
            if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(OPTS_UTF8, "ON"))) {
                localCharset = CHARSET_UTF8;
            }
            directory = new String(ftpPath.getBytes(localCharset), serverCharset);
        } catch (Exception e) {
            e.printStackTrace();
//            CrawlerTool.systemout(  "路径编码转换失败" ,2);
        }
        return directory;
    }


}